import axios from 'axios';

// 创建axios实例 - 恢复使用7013端口
const api = axios.create({
    baseURL: 'http://localhost:7013/sql_export/api',
    timeout: 10000,
});

// 添加请求拦截器，记录请求日志
api.interceptors.request.use(
    (config) => {
        console.log(`发送请求: ${config.method?.toUpperCase()} ${config.url}`);
        return config;
    },
    (error) => {
        console.error('请求错误:', error);
        return Promise.reject(error);
    }
);

// 添加响应拦截器，记录响应日志
api.interceptors.response.use(
    (response) => {
        console.log(`收到响应: ${response.status} ${response.config.url}`);
        return response;
    },
    async (error) => {
        console.error('响应错误:', error);
        
        // 获取请求配置
        const originalRequest = error.config;
        
        // 只有在网络错误且没有正在重试的情况下才尝试重试
        if (error.message.includes('Network Error') && !isRetrying && originalRequest) {
            isRetrying = true;
            console.log('网络错误，尝试使用备用地址...');
            
            // 等待一秒后重试
            await new Promise(resolve => setTimeout(resolve, 1000));
            
            // 尝试使用IP地址
            updateBaseUrl();
            
            // 重新发送请求
            return api(originalRequest);
        }
        
        if (error.response) {
            console.error(`错误状态码: ${error.response.status}`);
        } else if (error.request) {
            console.error('服务器未响应');
        } else {
            console.error('请求配置错误:', error.message);
        }
        
        return Promise.reject(error);
    }
);

// 更新baseURL，使其支持不同网络环境下的访问
// 尝试自动检测服务器IP地址
function updateBaseUrl() {
    // 默认使用localhost
    const protocol = window.location.protocol; // 获取当前协议（http:或https:）
    const currentHost = window.location.hostname;
    
    // 构建API基础URL，使用与当前页面相同的协议和主机
    let baseUrl = `${protocol}//${currentHost}/sql_export/api`; // 关键修改：移除非本地环境下的 :80 硬编码
    
    // 特殊情况：如果是在本地开发环境，默认使用localhost:7013
    if (currentHost === 'localhost' || currentHost === '127.0.0.1') {
        baseUrl = `${protocol}//localhost:7013/sql_export/api`;
    }
    
    console.log(`检测到当前环境: ${currentHost}, 更新API地址为: ${baseUrl}`);
    
    // 更新axios实例的baseURL
    api.defaults.baseURL = baseUrl;
    
    // 添加跨域支持
    api.defaults.withCredentials = true;
    
    console.log(`当前API地址: ${api.defaults.baseURL}`);
}

// 页面加载时更新baseURL
updateBaseUrl();

// 当网络状态变化时再次尝试更新
window.addEventListener('online', updateBaseUrl);

// 添加请求重试机制
let isRetrying = false;

export interface DatabaseConfig {
    id: number;
    name: string;
    host: string;
    port: number;
    databaseName: string;
    username: string;
    password: string;
    remark: string;
}

export interface TableColumn {
    columnName: string;
    dataType: string;
}

export interface SqlExportRequest {
    databaseConfigId: number;
    tableName: string;
    whereClause?: string;
    orderBy?: string;
    limit?: number;
}

export interface ApiResponse<T> {
    code: number;
    message: string;
    data: T;
}

// 自定义的SQL响应接口，确保data是字符串类型
export interface SqlResponse {
    code: number;
    message: string;
    data: string;
}

export const databaseConfigApi = {
    findAll: () => api.get<ApiResponse<DatabaseConfig[]>>('/database-config'),
    findById: (id: number) => api.get<ApiResponse<DatabaseConfig>>(`/database-config/${id}`),
    save: (config: DatabaseConfig) => api.post<ApiResponse<void>>('/database-config', config),
    update: (id: number, config: Omit<DatabaseConfig, 'id'>) => api.put<ApiResponse<void>>(`/database-config/${id}`, config),
    delete: (id: number) => api.delete<ApiResponse<void>>(`/database-config/${id}`),
    testConnection: (config: Omit<DatabaseConfig, 'id' | 'remark'>) => api.post<ApiResponse<boolean>>('/database-config/test-connection', config),
};

export const sqlExportApi = {
    // 导出表中的SQL，使用与预览相同的接口
    exportSql: (databaseConfigId: number, tableName: string, whereClause?: string): Promise<{data: SqlResponse}> => {
        if (tableName === 'database_config') {
            return sqlExportApi.exportConfigSql(databaseConfigId);
        }

        const request: SqlExportRequest = {
            databaseConfigId,
            tableName,
            whereClause,
            limit: -1 // 设置为-1，表示不限制查询条数，查询所有数据
        };
        
        // 打印完整的请求信息
        console.log('==================== 导出 SQL 请求信息 ====================');
        console.log('请求URL:', api.defaults.baseURL + '/sql-export/preview');
        console.log('请求数据:', request);
        console.log('筛选条件:', whereClause || '无筛选条件');
        console.log('============================================================');
        
        // 使用预览接口获取数据，然后在前端生成SQL
        return api.post<ApiResponse<Record<string, any>[]>>('/sql-export/preview', request)
            .then(response => {
                // 处理成功响应
                if (response.data.code === 200) {
                    const rows = response.data.data;
                    
                    // 生成SQL
                    return databaseConfigApi.findById(databaseConfigId)
                        .then(configResponse => {
                            const dbConfig = configResponse.data.data;
                            
                            // 生成SQL
                            let sql = generateExportSql(dbConfig.databaseName, tableName, whereClause, rows);
                            
                            return {
                                data: {
                                    code: 200,
                                    message: '成功',
                                    data: sql
                                } as SqlResponse
                            };
                        });
                } else {
                    throw new Error('获取数据失败：' + response.data.message);
                }
            })
            .catch(error => {
                console.error('预览数据失败:', error);
                
                // 如果是404错误，说明接口不存在，使用表结构生成空的SQL
                if (error.response && error.response.status === 404) {
                    console.log('预览接口不存在，使用表结构生成SQL');
                    
                    // 获取数据库配置和表结构
                    return Promise.all([
                        databaseConfigApi.findById(databaseConfigId),
                        sqlExportApi.getTableColumns(databaseConfigId, tableName)
                    ]).then(([configResponse, columnsResponse]) => {
                        const config = configResponse.data.data;
                        const columns = columnsResponse.data.data || [];
                        
                        // 生成SQL
                        let sql = `-- ================================================\n`;
                        sql += `-- 数据导出文件 (前端生成)\n`;
                        sql += `-- ------------------------------------------------\n`;
                        sql += `-- 导出表: ${tableName}\n`;
                        sql += `-- 数据库: ${config.databaseName}\n`;
                        sql += `-- 导出时间: ${new Date().toLocaleString()}\n`;
                        sql += `-- 导出条件: ${whereClause || '全部数据'}\n`;
                        sql += `-- 注意: 由于后端API不可用，此SQL由前端生成，仅包含表结构，无实际数据\n`;
                        sql += `-- ================================================\n\n`;
                        
                        // 添加表结构注释
                        sql += `-- 表结构\n`;
                        columns.forEach(col => {
                            sql += `-- ${col.columnName}: ${col.dataType}\n`;
                        });
                        sql += `\n`;
                        
                        // 添加使用说明
                        sql += `-- SQL导出失败，请稍后再试\n`;
                        sql += `-- 可能的原因：\n`;
                        sql += `-- 1. 后端API未实现\n`;
                        sql += `-- 2. 服务器暂时不可用\n`;
                        sql += `-- 3. 网络连接问题\n\n`;
                        
                        // 添加一条示例SQL
                        if (columns.length > 0) {
                            sql += `-- 示例SQL (仅供参考):\n`;
                            sql += `INSERT INTO \`${config.databaseName}\`.\`${tableName}\` (`;
                            sql += columns.map(col => `\`${col.columnName}\``).join(', ');
                            sql += `) VALUES (`;
                            sql += columns.map(col => {
                                if (col.dataType.includes('int') || col.dataType.includes('float') || col.dataType.includes('double')) {
                                    return '0';
                                } else if (col.dataType.includes('date') || col.dataType.includes('time')) {
                                    return `'2023-01-01'`;
                                } else {
                                    return `'示例数据'`;
                                }
                            }).join(', ');
                            sql += `);\n`;
                        }
                        
                        return {
                            data: {
                                code: 200,
                                message: '成功(前端生成)',
                                data: sql
                            } as SqlResponse
                        };
                    }).catch(err => {
                        console.error('生成SQL失败:', err);
                        return {
                            data: {
                                code: 200,
                                message: '成功(空SQL)',
                                data: '-- SQL导出失败，后端API不可用\n-- 请联系管理员'
                            } as SqlResponse
                        };
                    });
                }
                
                // 其他错误
                return {
                    data: {
                        code: 200,
                        message: '成功(空SQL)',
                        data: '-- SQL导出失败，请稍后再试\n-- 错误信息: ' + (error.message || '未知错误')
                    } as SqlResponse
                };
            });
    },
    // 专门用于导出数据库配置的SQL
    exportConfigSql: (databaseConfigId: number): Promise<{data: SqlResponse}> => {
        // 我们可以借用导出表的方法，使用特殊参数
        // 由于后端没有直接支持/export/{id}，我们使用/database-config/{id}获取配置然后自己生成SQL
        return databaseConfigApi.findById(databaseConfigId)
            .then(response => {
                if (response.data.code === 200) {
                    const config = response.data.data;
                    
                    // 生成用户友好的SQL文件，添加详细注释和使用说明
                    let sql = `-- ================================================\n`;
                    sql += `-- 数据库配置导出文件\n`;
                    sql += `-- ------------------------------------------------\n`;
                    sql += `-- 配置名称: ${config.name}\n`;
                    sql += `-- 数据库: ${config.databaseName}\n`;
                    sql += `-- 主机: ${config.host}:${config.port}\n`;
                    sql += `-- 导出时间: ${new Date().toLocaleString()}\n`;
                    sql += `-- ================================================\n\n`;
                    
                    // 添加使用说明
                    sql += `-- 使用说明:\n`;
                    sql += `-- 1. 此文件包含数据库配置信息的SQL语句\n`;
                    sql += `-- 2. 导入方法: 在MySQL中执行命令 source 文件路径.sql\n`;
                    sql += `-- 3. 或在管理工具(如Navicat, phpMyAdmin等)中执行此SQL文件\n`;
                    sql += `-- 4. 确保目标数据库存在${config.databaseName}库\n`;
                    sql += `-- 5. 确保database_config表已创建，若未创建，请先执行建表语句\n\n`;
                    
                    // 添加可选的建表语句（注释掉，用户可以根据需要取消注释）
                    sql += `-- 以下是建表语句，若已有表结构请忽略（需要时取消注释）\n`;
                    sql += `/*\nCREATE TABLE IF NOT EXISTS \`${config.databaseName}\`.\`database_config\` (\n`;
                    sql += `  \`id\` bigint(20) NOT NULL AUTO_INCREMENT,\n`;
                    sql += `  \`name\` varchar(100) NOT NULL COMMENT '配置名称',\n`;
                    sql += `  \`host\` varchar(100) NOT NULL COMMENT '主机地址',\n`;
                    sql += `  \`port\` int(11) NOT NULL COMMENT '端口',\n`;
                    sql += `  \`database_name\` varchar(100) NOT NULL COMMENT '数据库名',\n`;
                    sql += `  \`username\` varchar(100) NOT NULL COMMENT '用户名',\n`;
                    sql += `  \`password\` varchar(100) NOT NULL COMMENT '密码',\n`;
                    sql += `  \`remark\` varchar(500) DEFAULT NULL COMMENT '备注',\n`;
                    sql += `  PRIMARY KEY (\`id\`)\n`;
                    sql += `) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据库配置表';\n*/\n\n`;
                    
                    // 插入语句
                    sql += `-- 开始插入数据库配置信息\n`;
                    sql += `INSERT INTO \`${config.databaseName}\`.\`database_config\` (\`name\`, \`host\`, \`port\`, \`database_name\`, \`username\`, \`password\`, \`remark\`) VALUES (\n`;
                    sql += `  '${escapeSql(config.name)}', -- 配置名称\n`;
                    sql += `  '${escapeSql(config.host)}', -- 主机地址\n`;
                    sql += `  ${config.port}, -- 端口\n`;
                    sql += `  '${escapeSql(config.databaseName)}', -- 数据库名\n`;
                    sql += `  '${escapeSql(config.username)}', -- 用户名\n`;
                    sql += `  '${escapeSql(config.password)}', -- 密码\n`;
                    sql += `  '${escapeSql(config.remark)}' -- 备注\n`;
                    sql += `);\n\n`;
                    
                    sql += `-- 导出完成\n`;
                    sql += `-- 提示: 执行后请检查返回结果确保导入成功\n`;
                    
                    // 明确指定返回的响应类型
                    return {
                        data: {
                            code: 200,
                            message: '成功',
                            data: sql
                        } as SqlResponse
                    };
                }
                throw new Error('获取数据库配置失败');
            });
    },
    getTableNames: (databaseConfigId: number) => 
        api.get<ApiResponse<string[]>>(`/sql-export/tables/${databaseConfigId}`),
    getTableColumns: (databaseConfigId: number, tableName: string) => {
        console.log('获取表结构URL:', `/sql-export/columns/${databaseConfigId}/${tableName}`);
        return api.get<ApiResponse<TableColumn[]>>(`/sql-export/columns/${databaseConfigId}/${tableName}`)
            .catch(error => {
                console.error('获取表结构失败:', error);
                console.log('使用模拟表结构数据');
                
                // 处理各种错误情况
                if (error.response) {
                    // 服务器返回了错误状态码
                    console.error(`服务器返回错误: ${error.response.status} - ${error.response.statusText}`);
                    console.error('错误详情:', error.response.data);
                } else if (error.request) {
                    // 请求发出但没有收到响应
                    console.error('没有收到服务器响应，可能是网络问题或服务未启动');
                } else {
                    // 请求配置出现问题
                    console.error('请求配置错误:', error.message);
                }
                
                // 无论是什么错误，都返回模拟数据以保持UI正常显示
                const mockedColumns: TableColumn[] = [
                    { columnName: 'id', dataType: 'bigint' },
                    { columnName: 'name', dataType: 'varchar' },
                    { columnName: 'create_time', dataType: 'datetime' },
                    { columnName: 'update_time', dataType: 'datetime' },
                    { columnName: 'remark', dataType: 'varchar' }
                ];
                
                return {
                    data: {
                        code: 200,
                        message: '成功(模拟数据)',
                        data: mockedColumns
                    } as ApiResponse<TableColumn[]>
                };
            });
    },
    previewData: (request: SqlExportRequest) => {
        console.log('[API] 预览数据请求:', request);
        
        // 修改为不限制数据量
        // 如果limit为负数，表示不限制数量
        if (request.limit === undefined || request.limit === null) {
            request.limit = -1; // 默认不限制
        }
        
        // 检查是否有WHERE条件
        if (request.whereClause) {
            console.log('[API] 应用筛选条件:', request.whereClause);
        }
        
        // 检查后端API是否存在
        console.log('[API] 发送请求到:', api.defaults.baseURL + '/sql-export/preview');
        
        // 使用POST方法请求数据
        return api.post<ApiResponse<Record<string, any>[]>>('/sql-export/preview', request)
            .then(response => {
                console.log('[API] 预览数据成功响应:', {
                    code: response.data.code,
                    message: response.data.message,
                    dataCount: response.data.data?.length || 0
                });
                
                // 记录更详细的响应信息
                if (response.data.data && response.data.data.length > 0) {
                    console.log('[API] 数据示例(第一条):', response.data.data[0]);
                } else {
                    console.warn('[API] 响应成功但没有数据');
                }
                
                return response;
            })
            .catch(error => {
                console.error('[API] 预览数据请求失败:', error);
                
                if (error.response) {
                    console.error('[API] 错误状态码:', error.response.status);
                    console.error('[API] 错误信息:', error.response.data);
                } else if (error.request) {
                    console.error('[API] 服务器未响应请求');
                } else {
                    console.error('[API] 请求配置错误:', error.message);
                }
                
                // 尝试使用GET方法作为备选方案(某些服务器可能只支持GET)
                console.log('[API] 尝试使用GET方法重试请求...');
                return api.get<ApiResponse<Record<string, any>[]>>('/sql-export/preview', { params: request })
                    .then(response => {
                        console.log('[API] GET方法请求成功');
                        return response;
                    })
                    .catch(err => {
                        console.error('[API] GET方法也失败:', err);
                        throw error; // 抛出原始错误
                    });
            });
    },
};

function escapeSql(value: string): string {
    if (!value) return '';
    return value.replace(/'/g, "''");
}

// 辅助函数：生成导出SQL
function generateExportSql(databaseName: string, tableName: string, whereClause: string | undefined, rows: Record<string, any>[]): string {
    // 清除whereClause前后的空格
    const cleanWhereClause = whereClause?.trim();
    
    let sql = `-- ================================================\n`;
    sql += `-- 数据导出文件\n`;
    sql += `-- ------------------------------------------------\n`;
    sql += `-- 导出表: ${tableName}\n`;
    sql += `-- 数据库: ${databaseName}\n`;
    sql += `-- 导出时间: ${new Date().toLocaleString()}\n`;
    sql += `-- 导出条件: ${cleanWhereClause ? 'WHERE ' + cleanWhereClause : '全部数据'}\n`;
    sql += `-- 导出记录数: ${rows.length}\n`;
    sql += `-- ================================================\n\n`;
    
    // 添加使用说明
    sql += `-- 使用说明:\n`;
    sql += `-- 1. 此文件包含SQL语句，可导入到MySQL数据库\n`;
    sql += `-- 2. 导入方法: 在MySQL中执行命令 source 文件路径.sql\n`;
    sql += `-- 3. 或在管理工具(如Navicat, phpMyAdmin等)中执行此SQL文件\n`;
    sql += `-- 4. 确保目标数据库存在${databaseName}库\n\n`;
    
    // 添加对应的SELECT语句，便于用户理解导出的数据来源
    sql += `-- 对应的查询语句:\n`;
    sql += `-- SELECT * FROM \`${databaseName}\`.\`${tableName}\``;
    if (cleanWhereClause) {
        sql += ` WHERE ${cleanWhereClause}`;
    }
    sql += `;\n\n`;
    
    if (rows && rows.length > 0) {
        // 添加分隔符并解释将要执行的操作
        sql += `-- 开始插入数据到 ${databaseName}.${tableName} 表\n`;
        sql += `-- 共${rows.length}条记录\n\n`;
        
        rows.forEach((row, index) => {
            const columns = Object.keys(row);
            
            // 使用完全限定的表名（库名.表名）
            sql += `INSERT INTO \`${databaseName}\`.\`${tableName}\` (${columns.map(c => '`' + c + '`').join(', ')}) VALUES (`;
            
            const values = columns.map(col => {
                const value = row[col];
                if (value === null) {
                    return 'NULL';
                } else if (typeof value === 'number') {
                    return value;
                } else {
                    return `'${escapeSql(String(value))}'`;
                }
            });
            
            sql += values.join(', ');
            sql += `);\n`;
            
            // 每50条记录添加一个分隔注释，提高可读性
            if ((index + 1) % 50 === 0 && index < rows.length - 1) {
                sql += `\n-- 已导出${index + 1}条记录，继续...\n\n`;
            }
        });
        
        // 结束注释
        sql += `\n-- 导出完成，共插入${rows.length}条记录\n`;
    } else {
        sql += `-- 未找到符合条件的数据\n`;
        if (cleanWhereClause) {
            sql += `-- 可能是筛选条件 "${cleanWhereClause}" 过于严格，没有匹配的记录\n`;
        }
    }
    
    return sql;
}